package w.z.x.framework.repository.structures;

import lombok.Data;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 片段
 *
 * @author 魏祖潇
 */
@Data
public class Segment implements Serializable {
    private static final long serialVersionUID = -1L;

    /**
     * 字段
     */
    private Object field;

    /**
     * 运算符
     */
    private String operator;

    /**
     * 值
     */
    private Object value;

    /**
     * 子片段
     */
    private Collection<Segment> children;

    /**
     * 构建
     *
     * @param field    字段
     * @param operator 操作
     * @param value    值
     * @return 片段
     */
    public static Segment build(Object field, String operator, Object value) {
        Segment it = new Segment();
        it.field = field;
        it.operator = operator;
        it.value = value;
        it.children = null;
        return it;
    }

    /**
     * 追加子片段
     *
     * @param segment 片段
     */
    public void append(Segment... segment) {
        synchronized (this) {
            if (Objects.isNull(this.children)) {
                this.children = new ArrayList<>();
            }
        }
        this.children.addAll(Arrays.asList(segment));
    }

    /**
     * 追加子片段
     *
     * @param segments 片段
     */
    public void append(Collection<Segment> segments) {
        synchronized (this) {
            if (Objects.isNull(this.children)) {
                this.children = new ArrayList<>();
            }
        }
        this.children.addAll(segments);
    }

    /**
     * 获取值
     *
     * @return 值
     */
    public Collection<Object> values() {
        Collection<Object> collection = new ArrayList<>();
        if (Objects.nonNull(this.value)) {
            if (this.value.getClass().isArray()) {
                collection.addAll(Arrays.asList(this.value));
            } else if (this.value instanceof Collection) {
                collection.addAll((Collection) this.value);
            } else {
                collection.add(this.value);
            }
        }
        if (Objects.nonNull(this.getChildren()) && !this.children.isEmpty()) {
            this.children.stream().forEach(child -> {
                collection.addAll(child.values());
            });
        }
        return collection;
    }
}
